// Button.cpp
//
// A class for GUI buttons
//
// Nick Kitten
// 2009

#include "Button.h"

Button::Button()
{
}

/** 
 * Constructor: spriteFile is the name of an image which contains three equally-sized images in a row:
 * First is the plain button image, second is the mouse-over image, and third is the click image.
 * ID is the DarkGDK image and sprite number used to store the sprite, callback is a pointer
 * to the callback function used to handle mouse clicks, x and y are the position of the button,
 * and the width and height are the dimensions of the button.  If specified, the image will be scaled
 * to fit the given dimensions, and if the default values of -1 are used, they will be determined
 * from the image dimensions.  The top left pixel will be used to determine what color is transparent.
 */

Button::Button( char * spriteFile, int ID, char * text, int x, int y, void (*leftCallback)(), 
			   void (*rightCallback)(), int width, int height )
: leftClickFunc( leftCallback ), rightClickFunc( rightCallback ), buttonPressed( 0 ), lastPressed( 0 )
{
	// If right-click callback function was left blank, use same handler as for left click
	if( ! rightClickFunc )
		rightClickFunc = leftClickFunc;

	// Creates a sprite with 3 frames, stored in a row
	sCreateAnimatedSprite( ID, spriteFile, 3, 1, ID + 2000 );
	id = ID;

	// Load image into bitmap for modification (adding text), and to determine the image dimensions
	if( width == -1 || height == -1 )
	{
		sLoadBitmap( spriteFile, TEMP_BITMAP );
		width = dbBitmapWidth( TEMP_BITMAP ) / 3;
		height = dbBitmapHeight( TEMP_BITMAP );
	}
	else
	{
		sSizeSprite( ID, width, height );
		sCreateBitmap( TEMP_BITMAP, width * 3, height );
		sLoadBitmap( spriteFile, SCALED_BITMAP );

		int origWidth = dbBitmapWidth( SCALED_BITMAP );
		int origHeight = dbBitmapHeight( SCALED_BITMAP );

		dbCopyBitmap( SCALED_BITMAP, 0, 0, origWidth, origHeight, TEMP_BITMAP, 0, 0, width * 3, height );
		dbSleep( 10 );
	}

	int centerX = width / 2;
	int centerY = height / 2;

	dbSetCurrentBitmap( TEMP_BITMAP );
	dbSleep(10);

	// Set transparent color to top left corner
	DWORD transpColor = dbPoint( 0, 0 );
	dbSetImageColorKey( dbRGBR( transpColor ), dbRGBG( transpColor ), dbRGBB( transpColor ) );

	// Draw the text onto the button, using a different color for clicked frame
	DWORD unclickedColor = dbRGB( 0, 0, 0 ); // black
	DWORD clickedColor = dbRGB( 255, 0, 0 ); // red

	// Write on unclicked button image
	dbInk( unclickedColor, unclickedColor );
	dbCenterText( centerX, centerY - 5, text );

	// Write on mouseOver button image
	dbCenterText( centerX + width, centerY - 5, text );

	// Write on clicked button image
	dbInk( clickedColor, clickedColor );
	dbCenterText( centerX + 2 * width, centerY - 5, text );

	// Copy the modified image to the sprite
	dbGetImage( ID + 1000, 0, 0, width * 3, height, 1 );

	// Set up the hit area
	hitBox.minPoint = Position( x, y );
	hitBox.maxPoint = Position( x + width, y + height );

	// Make visible by default
	setVisible( true );

	// Restores default drawing to screen
	dbSetCurrentBitmap( 0 );

}

Button::~Button()
{
	if( dbSpriteExist( getID() ) )
		dbDeleteSprite( getID() );

	if( dbImageExist( getID() ) )
		dbDeleteImage( getID() );

	if( dbBitmapExist( TEMP_BITMAP ) )
		dbDeleteBitmap( TEMP_BITMAP );
}

int Button::getID() const
{
	return id;
}

bool Button::getVisible() const
{
	return visible;
}

void Button::setVisible(bool visibility)
{
	visible = visibility;
	if( visible )
		dbShowSprite( getID() );
	else
		dbHideSprite( getID() );
}

	// Checks if the pixel is within the hit area of the button
bool Button::inRect( int x, int y ) const
{
	return ( x > hitBox.minPoint.x && x < hitBox.maxPoint.x &&
		y > hitBox.minPoint.y && y < hitBox.maxPoint.y );
}

// Draws the button if its visible.  Also calls the click callback
// function if the user has (right- or left-) clicked on the button
void Button::display()
{
	if( ! getVisible() )
		return;

	Position mousePos = Position( dbMouseX(), dbMouseY() );

	lastPressed = buttonPressed;
	buttonPressed = dbMouseClick();

	if( inRect( mousePos.x, mousePos.y ) )
		if( ! buttonPressed )
		{
			dbSetSpriteFrame( getID(), 2 );

			// button clicked and released
			if( lastPressed == 1 )
				leftClickFunc();
			else if( lastPressed == 2 )
				rightClickFunc();
		}
		else
			dbSetSpriteFrame( getID(), 3 );
	else
		dbSetSpriteFrame( getID(), 1 );

	

	dbPasteSprite( getID(), hitBox.minPoint.x, hitBox.minPoint.y );

}
